//   YXC

1.插入一个数  			heap[++size]=x;up(size);
2.求集和当中的最小值	heap[1];
3.删除最小值			heap[1]=heap[size];size--;down(1);
4.删除任意一个元素		heap[k]=heap[size];size--;根据K的变化值来判断是 size--'还是 size++;
5.修改任意一个元素  	heap[k]=x;down(k);up(k);

#include <iostream>
#include <algorithm>

using namespace std;

const int N=100010;
int n,m;
int h[N],sz;

void down(int u){
    int t=u;
    if(u*2<=sz&&h[u*2]<h[t]) t=u*2;
    if(u*2+1<=sz&&h[u*2+1]<h[t]) t=u*2+1;
    if(u!=t){
        swap(h[u],h[t]);
        down(t);
    }
}

void up(int u){   //往上移
    while(u/2&&h[u/2]>h[u]){  //找到父节点，并判断我和父节点的大小
        swap(h[u/2],h[u]);
        u/=2;
    }
}

int main(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++) scanf("%d",&h[i]);
    
    sz=m;
	
    for(int i=m/2;i;i--) down(i);
	//这儿解释一下，我们由于完全二叉树的结构，我们知道n/2以上的都是在倒数第二层及其以上层，
	//所以我们就顺着往上down就可以了，而不用利用一个一个插入来做。 
	//这个操作的结果必然会把最小值放在顶层，不信可以追踪最小值的范围。
	//时间复杂度为o(n） 而不是nlog(n);
	

    while(n--){
        printf("%d ",h[1]);
        h[1]=h[sz];
        sz--;
        down(1);
    }
    return 0;
}
